package com.pactera.asmp.server.job.dispatch.impl.task;

import com.pactera.asmp.server.common.constants.TaskStatus;
import com.pactera.asmp.server.common.logprint.utils.CollectionUtils;
import com.pactera.asmp.server.dao.*;
import com.pactera.asmp.server.entity.*;
import com.pactera.asmp.server.pojo.*;
import lombok.extern.slf4j.Slf4j;

import org.quartz.CronExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 为了升级多机部署
 */
@Slf4j
@Component
public class TaskDataRepository {

    @Autowired
    private TaskDeviceMapper taskDeviceMapper;

    @Autowired
    private TaskMapper taskMapper;

    @Autowired
    private SubtaskMapper subtaskMapper;

    @Autowired
    private DeviceInfoMapper deviceInfoMapper;

    @Autowired
    private TCanInfoMapper tCanInfoMapper;

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private ProjectMapper projectMapper;

    @Autowired
    private TestReportMapper mTestReportMapper;

    @Autowired
    private SubtaskDistributeMapper subtaskDistributeMapper;

    public long countCanInfoByDuid(String duid){
        TCanInfoExample example = new TCanInfoExample();
        example.createCriteria().andDuidEqualTo(duid);
        long count = tCanInfoMapper.countByExample(example);
        return count;
    }

    public DeviceInfo getDeviceByDuid(String duid){
        return deviceInfoMapper.selectByDuid(duid);
    }

    @Transactional(rollbackFor=Exception.class)
    public void createTaskDeviceList(List<TaskDevice> taskDeviceList) throws Exception{
        for(TaskDevice td : taskDeviceList){
            taskDeviceMapper.insertSelective(td);
        }
    }

    public List<TaskDevice> getTaskDeviceListById(Integer taskId){
        TaskDeviceExample taskDeviceExample = new TaskDeviceExample();
        taskDeviceExample.createCriteria().andTaskIdEqualTo(Long.valueOf(taskId)).andIsDeletedEqualTo(0);
        return taskDeviceMapper.selectByExample(taskDeviceExample);
    }

    public List<Subtask> getSubtaskListByTaskId(Long taskId){
        SubtaskExample subtaskExample = new SubtaskExample();
        SubtaskExample.Criteria criteria = subtaskExample.createCriteria().andTaskIdEqualTo(taskId).andIsDeletedEqualTo(0);
        subtaskExample.setOrderByClause("id ASC");
        return subtaskMapper.selectByExample(subtaskExample);
    }

    @Transactional(rollbackFor=Exception.class)
    public boolean modifyTaskStatusById(Integer histTaskId, int status) throws Exception{
        TaskDTO histTask = taskMapper.getTaskHistoryById(histTaskId);
        histTask.setStatus(status);
        int rslt = taskMapper.updateHistory(histTask);
        if(rslt<1){
            throw new Exception();
        }
        TaskDTO task = taskMapper.getTaskById(histTask.getParentId());
        task.setStatus(status);
        rslt = taskMapper.update(task);
        if(rslt<1){
            throw new Exception();
        }
        return true;
    }

    @Transactional(rollbackFor=Exception.class)
    public boolean modifyTaskStatusAndTDListById(Integer histTaskId, int status, List<TaskDevice> tdList, int occupyStatus) throws Exception{
        TaskDTO histTask = taskMapper.getTaskHistoryById(histTaskId);
        histTask.setStatus(status);
        int rslt = taskMapper.updateHistory(histTask);
        if(rslt<1){
            throw new Exception();
        }
        TaskDTO task = taskMapper.getTaskById(histTask.getParentId());
        task.setStatus(status);
        rslt = taskMapper.update(task);
        if(rslt<1){
            throw new Exception();
        }
        for(TaskDevice taskDevice:tdList){
            taskDevice.setOccupyStatus(occupyStatus);
            taskDeviceMapper.updateByPrimaryKey(taskDevice);
        }
        // 更新父任务的状态
        return this.modifyTimerTaskStatus(histTask);
    }

    @Transactional(rollbackFor=Exception.class)
    public boolean modifyTask(TaskDTO histtask) throws Exception{
        int rslt = taskMapper.updateHistory(histtask);
        if(rslt<1){
            log.error("updateHistory error");
            return false;
        }
        histtask.setId(histtask.getParentId());
        histtask.setParentId(null);
        rslt = taskMapper.update(histtask);
        if(rslt<1){
            throw new Exception();
        }
        return rslt>0;
    }

    public boolean modifyTimerTaskStatus(TaskDTO histtask) throws Exception{
        TaskDTO pTask = taskMapper.getTaskById(histtask.getParentId());
        if(pTask != null) {
            if(pTask.getParentId()!=null) {
                TaskDTO tTask = taskMapper.getTaskById(pTask.getParentId());
                if (tTask != null) {
                    if(tTask.getType() == 4){
                        tTask.setSuccessNumber(tTask.getExeNumber());
                        tTask.setFailNumber(0);
                    }
                    if(tTask.getCycleType() == 1) {
                        tTask.setStatus(TaskStatus.TASK_COMPLETE.getValue());
                        int rslt = taskMapper.update(tTask);
                        if (rslt < 1) {
                            throw new Exception();
                        }
                        List<TaskDTO> listByParentid = taskMapper.getTaskHistListByParentid(new TaskSearchDTO() {{setParentId(tTask.getId());}});
                        for(TaskDTO histTask: listByParentid) {
                            histTask.setStatus(TaskStatus.TASK_COMPLETE.getValue());
                            taskMapper.updateHistory(histTask);
                        }
                    }else if(tTask.getCycleType() == 0) {
                        CronExpression cronExpression = new CronExpression(tTask.getCron());
                        Date exceDate = cronExpression.getNextValidTimeAfter(com.pactera.asmp.server.utils.DateUtil.toDate(pTask.getExecTime()));
                        LocalDateTime execTime = com.pactera.asmp.server.utils.DateUtil.toLocalDateTime(exceDate);
                        log.info("execTime:{}, exeEndTime:{}", execTime.toString(), tTask.getExeEndTime().toString());
                        if(execTime.isAfter(tTask.getExeEndTime())) {
                            tTask.setStatus(TaskStatus.TASK_COMPLETE.getValue());
                            int rslt = taskMapper.update(tTask);
                            if (rslt < 1) {
                                throw new Exception();
                            }
                            List<TaskDTO> listByParentid = taskMapper.getTaskHistListByParentid(new TaskSearchDTO() {{setParentId(tTask.getId());}});
                            for(TaskDTO histTask: listByParentid) {
                                histTask.setStatus(TaskStatus.TASK_COMPLETE.getValue());
                                taskMapper.updateHistory(histTask);
                            }
                        }
                    }
                    
                }
            }
        }else{
            return false;
        }
        return true;
    }


    public List<TaskDTO> getTaskListByStatus(int status){
        List<TaskDTO> rsltList = new ArrayList<TaskDTO>();
        TaskSearchDTO taskSearchDTO = new TaskSearchDTO();
        taskSearchDTO.setStatus(status);
        List<TaskDTO> taskList = taskMapper.getTaskList(taskSearchDTO);
        if(CollectionUtils.isNotEmpty(taskList)) {
            for (TaskDTO task : taskList) {
                TaskDTO taskHist = taskMapper.getLastTaskHistoryByTaskId(task.getId());
                if(taskHist!=null){
                    rsltList.add(taskHist);
                }
            }
        }
        return rsltList;
    }

    public TaskDTO  getTaskHistoryById(Integer taskId){
        return taskMapper.getTaskHistoryById(taskId);
    }

    public List<TaskDevice> getTaskDeviceListByDeviceAndStatus(String duid, int occupyStatus) {
        TaskDeviceExample taskDeviceExample = new TaskDeviceExample();
        taskDeviceExample.createCriteria().andDuidEqualTo(duid).andOccupyStatusEqualTo(occupyStatus).andIsDeletedEqualTo(0);
        return taskDeviceMapper.selectByExample(taskDeviceExample);
    }



    public User findUserById(Integer id) {
        return userMapper.findUserById(id);
    }

    public List<User> findUserByIds(List<Integer> list) {
        return userMapper.selectByPrimaryKeys(list);
    }


    public SubtaskDistribute getSubtaskDistributeByTaskId(Long taskId){
        SubtaskDistributeExample example = new SubtaskDistributeExample();
        example.createCriteria().andTaskIdEqualTo(taskId).andIsDeletedEqualTo(0);
        List<SubtaskDistribute> list = subtaskDistributeMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(list)){
            return null;
        }
        return list.get(0);
    }

    public List<TestReport> queryTestReportList(TestReportSearchDTO testReportSearchDTO){
        List<TestReport> list = mTestReportMapper.select2(testReportSearchDTO);
        return list;
    }

    public ProjectInfo getProjectInfo(Integer projectId){
        return  projectMapper.selectByPrimaryKey(projectId);
    }

}
